package ru.spbu.math.seabattle.entity;

import java.io.Serializable;

public class FieldModel implements Serializable {

	private static final long serialVersionUID = 1L;
	public final int FIELD_SIZE;
	private int activeCells = 0;
	
	public static enum Cell {
		EMPTY_CELL, SHIP, DAMAGED_SHIP, SHOT_CELL
	}
	
	private final Cell[][] field;
	
	public FieldModel(int fieldSize) {
		
		this.FIELD_SIZE = fieldSize;
		field = new Cell[fieldSize][fieldSize];
		for(int i = 0; i < fieldSize; i ++) {
			for(int j = 0; j < fieldSize; j ++) {
				setCell(i, j, Cell.EMPTY_CELL);
			}
		}
	}
	
	public FieldModel(FieldModel copyField) {
		
		FIELD_SIZE = copyField.FIELD_SIZE;
		activeCells = copyField.getActiveCells();
		field = new Cell[FIELD_SIZE][FIELD_SIZE];
				
		for (int i = 0; i < copyField.FIELD_SIZE; i++) {
			for (int j = 0; j < copyField.FIELD_SIZE; j++) {
				field[i][j] = copyField.getCell(i, j);
			}
		}
	}
	
	public int getActiveCells() {
		return activeCells;
	}
	
	private void check(int i, int j) {
		if (!isCell(i, j)) {
		//	throw new IllegalArgumentException("x and y must be in 0 : " + fieldSize + ". The value of x is " + i + ", the value of y is " + yCoordinate);
		}
	}
	
	public Cell getCell(int i, int j) {
		check(i, j);
		return field[i][j];
	}
	
	public void setCell(int i, int j, Cell cell) {
		check(i, j);
		field[i][j] = cell;
		if (cell == Cell.SHIP) activeCells++;
		if (cell == Cell.DAMAGED_SHIP) activeCells--;
	}
	
	public void setShipCell(int i, int j) {
		check(i, j);
		setCell(i, j, Cell.SHIP);
	}
	
	public void setShotCell(int i, int j) {
		check(i, j);
		setCell(i, j, Cell.SHOT_CELL);
	}
	
	public boolean isShipCell(int i, int j) {
		check(i, j);
		return field[i][j] == Cell.SHIP;
	}
	
	public boolean isShipCell(Action action) {
		check(action.i, action.j);
		return field[action.i][action.j] == Cell.SHIP;
	}
	
	public boolean isDemagedShipCell(int i, int j) {
		check(i, j);
		return field[i][j] == Cell.DAMAGED_SHIP;
	}
	
	public boolean isEmptyCell(int i, int j) {
		check(i, j);
		return field[i][j] == Cell.EMPTY_CELL;
	}
	
	public boolean isShotCell(int i, int j) {
		check(i, j);
		return field[i][j] == Cell.SHOT_CELL;
	}
	
	// this method checks if cell is available for placing a ship there
	public boolean isAvailableCell(int i, int j) {

		if (!isCell(i, j)) return false;
		if (!isEmptyCell(i, j)) return false;
		for (int ii = -1; ii <= 1; ii++) {
			for (int jj = -1; jj <= 1; jj++) {
				if (ii == 0 && jj == 0) continue;
				if (!isCell(i + ii, j + jj)) continue;
				if (!isEmptyCell(i + ii, j + jj) && !isShotCell(i + ii, j + jj)) return false;
			}
		}
		return true;
	}

	private boolean isCell(int i, int j) {
		if (i >= 0 && i < FIELD_SIZE && j >= 0 && j < FIELD_SIZE) return true;
		return false;
	}
	
	public void print() {
		for (int i = 0; i < FIELD_SIZE; i++) {
			for (int j = 0; j < FIELD_SIZE; j++) {
				System.out.print(((field[i][j] == Cell.SHIP) ? "1" : "0") + " ");
			}
			System.out.println();
		}
	}
}
